home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
101-125
/
105
/
pere-et-fils
/
fils.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-13
|
7KB
|
209 lines
/**********************************************************************
*
* fichier: fils.c Terminal sur une fenetre Amiga.
* le code est reentrant pour permettre le
* lancement de plusieurs process dessus.
* Pour cela, il doit etre linke avec
* 'startproc.obj' qui est reentrant aussi
* et remplace 'astartup.obj'.
* StartProc.obj permet seulement d'avoir
* une fonction "exit()" et SysBase.
*
* par Jean-Michel FORGEAS
*
* creation: 09-Jun-87
* revision: 18-Jun-87
*
**********************************************************************/
/******* Included Files ***********************************************/
#include "proc.h"
/******* Imported *****************************************************/
extern ULONG SysBase; /* = AbsExecBase seule adresse
absolue dans Exec */
extern struct Pack *GetMsg();
extern struct FileHandle *Open();
/******* Exported ******************************************************/
VOID main();
/******* Program ******************************************************/
static VOID Quitte();
/* ATTENTION!!! DOSBase est GLOBAL au
programme, si un process ecris alors
qu'un autre lis, ca fait desordre !!!
*/
struct DosLibrary *DOSBase=0;
/* chaque fils a besoin de ses variables globales, mais
elles doivent leur etre propre. Donc chaque fils va
allouer de la memoire a l'image de cette structure
et va ranger ses variables dedans.
*/
struct Global {
int id; /* numero du process */
struct MsgPort *port; /* port original du process */
struct Pack *pack; /* message recu du pere */
struct FileHandle *stdin, *stdout, *stderr; /* fichier d'e/s */
int initialSP; /* pointeur initial sur la pile du process */
}; /* il est passe par startproc.obj et doit */
/* lui etre retourne avec exit(initialSP); */
/**********************************************************************
*
* Point d'entree
*
**********************************************************************/
/*-------------------------------------------------------------
* lancement de chaque fils
*/
VOID main(initialSP) /* chaque process a un pointeur sur sa pile. Ici il */
int initialSP; /* est passe au process par 'startproc.obj' pour le */
/* memoriser et le rendre avec exit(initialSP) */
{
struct Global *G=0; /* pointeur sur la zone des variables du process */
struct Process *proc; /* process de chaque fils pour trouver le port */
struct MsgPort *port; /* adresse du port original du process */
struct Pack *pack; /* adresse du message venant du pere */
int rc;
if (!DOSBase) {
Forbid(); /* bloque les autre process pendant que celui-ci ecrit */
DOSBase = (struct DosLibrary *) OpenLibrary( DOSNAME, 0 );
if (!DOSBase) exit(0);
Permit(); /* les autres peuvent maintenant lire */
}
proc = (struct Process *) FindTask(0); /* adresse de son descripteur...*/
port = &proc->pr_MsgPort; /* ...pour adresse de son port */
WaitPort( port ); /* attend le message du pere avec infos */
pack = GetMsg( port ); /* sur fichier a ouvrir */
/*--- allocation de memoire pour les variables globales ---*/
if (!(G = (struct Global *) AllocMem( sizeof(struct Global), MEMF_CLEAR )))
{
Quitte( G, NO_MEMORY );
}
/*--- initialisation des variables globales ---*/
if ((rc = InitGlobal( G, initialSP, pack )) != NO_ERROR)
{
Quitte( G, rc );
}
pack->result = NO_ERROR; /* le pere veut savoir si tout est OK */
pack->FilsPort = G->port; /* le pere sait de qui vient le reply */
ReplyMsg( pack );
/* Appel fonction principale */
rc = ProcessCode( G );
Quitte( G, rc );
}
/*-------------------------------------------------------------
* Initialisation de l'environement de chaque fils
*/
static int InitGlobal( G, initialSP, pack )
struct Global *G;
int initialSP;
struct Pack *pack;
{
struct MsgPort *port;
G->id = pack->id; /* numero */
G->initialSP = initialSP; /* pointeur de pile passe par startproc.obj */
/* chacun ouvre son fichier (console) */
if (!(port = (struct MsgPort *) CreatePort( "fils", 0 ))) return( NO_MEMORY );
G->port = port;
if (!(G->stdin = Open( pack->bufread, MODE_OLDFILE ))) return( NO_FILE );
G->stdout = G->stderr = G->stdin;
Write( G->stdout, "stdout ok\n", 10 );
return( NO_ERROR );
}
/*-------------------------------------------------------------
* Nettoie et fin
*/
static VOID Quitte( G, rc )
struct Global *G;
int rc;
{
int initialSP;
struct Pack *pack;
initialSP = G->initialSP; /* rememoriser initialSP avant FreeMem() */
pack = G->pack; /* l'adresse du message aussi */
Write( G->stdout, "Quitte() ok\n", 12 );
if (G->stdin) Close( G->stdin );
if (G->port) DeletePort( G->port );
if (G) FreeMem( G, sizeof(struct Global) );
if (DOSBase) CloseLibrary( DOSBase );
Forbid(); /* bloque le pere: il faut que le process se */
/* termine avant que le pere fasse UnLoad du code */
pack->result = rc;
ReplyMsg( pack ); /* pour que le pere sache qu'il peut faire UnLoad */
/* si c'est le dernier fils */
exit(initialSP); /* retour a startproc.obj qui va remettre son */
/* pointeur de pile a cette valeur avant RTS */
}
/*-------------------------------------------------------------
* code de fonctionnement de chaque process fils
*/
static int ProcessCode(G)
struct Global *G;
{
Write( G->stdout, "Process Fils prêt\n", 18 ); /*accueil */
while (TRUE)
{
WaitPort( G->port ); /* attend une requete du pere */
G->pack = GetMsg( G->port );
if (G->pack->lenwrite)
{
Write( G->stdout, G->pack->bufwrite, G->pack->lenwrite );
G->pack->lenwrite = 0;
}
if (G->pack->cmd == CMD_STOP) break;
G->pack->lenread = Read( G->stdin, G->pack->bufread, G->pack->lenread );
/* renvoit les caracteres lu au pere. Si c'est 'logoff', le */
/* pere renverra un CMD_STOP */
ReplyMsg( G->pack );
}
return( NO_ERROR );
}